"""
_______________________________________________________算法执行区_________________________________________________________________________________________

"""
import time


class NEH:
    # 成员变量
    proc_list = []

    # 构造方法
    def __init__(self, proc_list):
        self.proc_list = proc_list
        self.allTimes =0

    # 排序函数
    def xum(self, xmm):
        sum = 0
        for i in range(len(xmm)):
            sum += xmm[i]
        return sum

    def neh(self):
        """
           #param list:proc 每个工件在每个机器上的加工时间
        """
        """
        进行ENH计算
        """
        # step1:求每个工序在每台机器上的加工时间总长，按递减顺序排列
        """
        冒泡算法复杂度:n^3
        """
        # self.proc_list = self.DescSort(self.proc_list)
        # print(f"proc(按总时长降序排列):{self.proc_list}")

        """
        内置:TimSort
        """
        start=time.perf_counter()
        self.proc_list.sort(key=self.xum, reverse=True)
        print(f"proc(按总时长降序排列):{self.proc_list}")

        # 第二步取出第一步的前两个工序，即优先权数最大的两个工序；第三部将剩余的工序逐次插入第二步的结果中，插入的位置使得makespan最小
        # step2:这里优化为一步,可以保留index=0的工序,依次插入index=1,2,3,....,每次插入得出的最优工序排序就保留,然后还是依次插入
        resultProcList = self.TranTo(self.proc_list)
        end=time.perf_counter()
        self.allTimes=end-start
        print("总时间:",self.allTimes)
        print("\n最终的排序", resultProcList)
        return

    # def DescSort(self, proc_list):
    #     """
    #     #param list:proc 每个工件在每个机器上的加工时间
    #     """
    #     # 利用冒泡算法对list列表进行降序排列
    #
    #     # 得出list列表的长度
    #     jobQty = len(proc_list)
    #
    #     """
    #     以下是冒泡
    #     """
    #     for i in range(jobQty - 1, 0, -1):
    #         for j in range(i):
    #             sumi = 0
    #             sumii = 0
    #             for listi in (proc_list[j]):
    #                 sumi += listi
    #             for listii in (proc_list[j + 1]):
    #                 sumii += listii
    #
    #             if (sumi < sumii):
    #                 temp = proc_list[j]
    #                 proc_list[j] = proc_list[j + 1]
    #                 proc_list[j + 1] = temp
    #     return proc_list  # 返回降序之后的排序

    def getPFMsh(self, ptims, seq):
        """
        Param:ptim:给定的要排序的序列,
        Parm: seq:给定要排序列表的先后顺序  eg:list=[[4,1,6],[2,4,3]] seq=[0,1]就是以 先加工..工件[4,1,6] 然后加工..工件[2,4,3]得出最后工序完成时间,反之就是[2,4,3]  [4,1,6]
        """
        jobQty = len(ptims)  # 工件数

        machQty = len(ptims[0])  # 机器数

        schedule = []
        # colum1:加工工件序号;column2:加工所需机器的序号(加工顺序);column3:每个工件在相应机器上的加工时间;column4:开始加工时间startTime;column5:endTime

        # ----------------------------------------------------------------
        """
        不懂的去写几个简单的数据eg:list=[[4,1,6],[2,4,3]];去调试
        """
        # 记录工件的加工时间
        jobCanStartTime = [0] * jobQty
        # 记录机器上的加工时间
        machCanStartTime = [0] * machQty

        for i in range(jobQty):
            for j in range(machQty):
                # 定义一个临时的列表储存:一行这个:colum1:加工工件序号;column2:加工所需机器的序号(加工顺序);column3:每个工件在相应机器上的加工时间;column4:开始加工时间startTime;column5:endTime
                templist = []
                # 求得加工开始时间
                canStartTime = max(jobCanStartTime[i], machCanStartTime[j])
                # 求得结束时间
                endTime = canStartTime + ptims[i][j]
                # 给templist添加 colum1:加工工件序号;column2:加工所需机器的序号(加工顺序);column3:每个工件在相应机器上的加工时间;column4:开始加工时间startTime;column5:endTime
                templist.extend([seq[i], j, ptims[i][j], canStartTime, endTime])
                # 给schedule添加相应数据
                schedule.append(templist)

                """
                以下就是要调试,也可以试着看懂
                """
                jobCanStartTime[i] = endTime
                machCanStartTime[j] = endTime

        # print(schedule)
        # print("{seq[i]}")
        # print(jobQty*machQty)

        print("------------------schedule-------------------------")
        print("工件序号  机器序号   加工时间    startTime    endTime")
        for d in range(jobQty * machQty):
            for p in range(5):
                print(schedule[d][p], end="          ")
            print('\n')

        # 得出以[0,1]或者[1,0]顺序加工完成所需的时间
        ENDTime = schedule[jobQty * machQty - 1][4]

        return ENDTime

    def TranTo(self, proc_list):
        # 定义一个加工顺序列表
        seq_list = [0]
        # 因为我把原本的2,3步合并这里我们直接从1开始插入

        i = 1

        for i in range(1, len(proc_list)):
            # 截取需要加工排序的列表
            SubTimeList = proc_list[0:i]
            # 截取需要排序的加工__顺序__列表
            Sub_Seq_list = seq_list[0:i]
            # 需要插入到加工排序的list
            InsertTimeList = proc_list[i]
            # 存储临时总加工时间
            Time = [0] * (len(SubTimeList) + 1)
            # 存储临时排序
            TempList = [0] * (len(SubTimeList) + 1)
            # 存储临时加工顺序列表
            Temp_Seq_List = [0] * (len(SubTimeList) + 1)
            # 计算需要插入的次数
            listlen = (len(SubTimeList) + 1)
            # 以下for循环就是遍历依次插入
            for j in range(listlen):
                # 把i插入到index:j位置到加工顺序列表
                Sub_Seq_list.insert(j, i)
                # 保存到加工顺序临时列表
                Temp_Seq_List[j] = Sub_Seq_list

                # 把InsertTimeList插入到index:j位置到加工顺序列表
                SubTimeList.insert(j, InsertTimeList)
                # 保存到加工临时列表
                TempList[j] = SubTimeList

                # 调用getPFMsh得出总加工完成时间
                Time[j] = (self.getPFMsh(SubTimeList, Sub_Seq_list))

                # 刷新缓存
                SubTimeList = proc_list[0:i]
                # 刷新缓存
                Sub_Seq_list = seq_list[0:i]
            # 得出Time列表最小的总加工时间
            Min = min(Time)
            # 根据得出的加工时间得出相应的index
            INDEX = Time.index(Min)

            # 更新加工顺序列表
            seq_list = Temp_Seq_List[INDEX]
            # 每次打印更新的列表
            print("________________________________更新加工顺序列表______________________________________")
            print("加工顺序集合列表", Temp_Seq_List)
            print("每种加工顺序对象的完工时间", Time)
            print("经过筛选每种加工顺序对应的完工时间,得出相对最优的加工顺序排序:")
            print("相对最优加工顺序:::", seq_list)

            # 更新加工列表
            print("\n_______________________________更新加工列表_________________________________________")
            print("根据相对最优加工顺序更新proc_list:")
            print("原先的proc_list:::", proc_list)
            jjj = 0
            for i in TempList[INDEX]:
                proc_list[jjj] = i
                jjj += 1
            # 打印更新的proc_list
            print("更新后proc_list:::", proc_list)

        return proc_list
